home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / sbin / deluser < prev    next >
Encoding:
Text File  |  2006-11-28  |  13.9 KB  |  482 lines

  1. #!/usr/bin/perl
  2.  
  3. # deluser -- a utility to remove users from the system
  4. # delgroup -- a utilty to remove groups from the system
  5. my $version = "3.100";
  6.  
  7. # Copyright (C) 2000 Roland Bauerschmidt <rb@debian.org>
  8. # Based on 'adduser' as pattern by
  9. #     Guy Maor <maor@debian.org>
  10. #     Ted Hajek <tedhajek@boombox.micro.umn.edu>
  11. #     Ian A. Murdock <imurdock@gnu.ai.mit.edu>
  12.  
  13. # This program is free software; you can redistribute it and/or modify
  14. # it under the terms of the GNU General Public License as published by
  15. # the Free Software Foundation; either version 2 of the License, or
  16. # (at your option) any later version.
  17. #
  18. # This program is distributed in the hope that it will be useful,
  19. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21. # GNU General Public License for more details.
  22. #
  23. # You should have received a copy of the GNU General Public License
  24. # along with this program; if not, write to the Free Software
  25. # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  26.  
  27. ####################
  28. # See the usage subroutine for explanation about how the program can be called
  29. ####################
  30.  
  31. use warnings;
  32. use strict;
  33. use Getopt::Long;
  34. use Debian::AdduserCommon;
  35.  
  36. my $install_more_packages ;
  37.  
  38. BEGIN {
  39.     eval 'use File::Find';
  40.     if ($@) {
  41.       $install_more_packages = 1;
  42.     }
  43.     #no warnings "File::Find";
  44.     eval 'use File::Temp';
  45.     if ($@) {
  46.       $install_more_packages = 1;
  47.     }
  48. }
  49.  
  50.  
  51. BEGIN {
  52.     eval 'use Locale::gettext';
  53.     if ($@) {
  54.         *gettext = sub { shift };
  55.         *textdomain = sub { "" };
  56.         *LC_MESSAGES = sub { 5 };
  57.     }
  58.     eval {
  59.         require POSIX;
  60.         import POSIX qw(setlocale);
  61.     };
  62.     if ($@) {
  63.         *setlocale = sub { return 1 };
  64.     }
  65. }
  66.  
  67. setlocale(LC_MESSAGES, "");
  68. textdomain("adduser");
  69.  
  70. my $action = $0 =~ /delgroup$/ ? "delgroup" : "deluser";
  71. our $verbose = 1;
  72. my %pconfig = ();
  73. my %config = ();
  74. my $configfile;
  75. my @defaults;
  76.  
  77. unless ( GetOptions ("quiet|q" => sub {$verbose = 0; },
  78.             "debug" => sub {$verbose = 2; },
  79.         "version|v" => sub { &version(); exit 0; },
  80.         "help|h" => sub { &usage(); exit 0;},
  81.         "group" => sub { $action = "delgroup";},
  82.         "conf=s" => \$configfile,
  83.         "system" => \$pconfig{"system"},
  84.         "only-if-empty" => \$pconfig{"only_if_empty"},
  85.         "remove-home" => \$pconfig{"remove_home"},
  86.         "remove-all-files" => \$pconfig{"remove_all_files"},
  87.         "backup" => \$pconfig{"backup"},
  88.         "backup-to=s" => \$pconfig{"backup_to"}
  89.        ) ) {
  90.     &usage;
  91.     exit 1;
  92. }
  93.  
  94. # everyone can issue "--help" and "--version", but only root can go on
  95. dief (gtx("Only root may remove a user or group from the system.\n")) if ($> != 0);
  96.  
  97. if (!defined($configfile)) { 
  98.     @defaults = ("/etc/adduser.conf", "/etc/deluser.conf");
  99. } else {
  100.     @defaults = ($configfile);
  101. }
  102.  
  103. my @names = ();
  104. my ($user,$group);
  105.  
  106. ######################
  107. # handling of @names #
  108. ######################
  109.  
  110. while (defined(my $arg = shift(@ARGV))) {
  111.   if (defined($names[0]) && $arg =~ /^--/) {
  112.       dief (gtx("No options allowed after names.\n"));
  113.     } else {            # it's a username
  114.     push (@names, $arg);
  115.     }
  116. }
  117.  
  118. if(@names == 0) {
  119.     if($action eq "delgroup") {
  120.     print (gtx("Enter a group name to remove: "));
  121.     } else {
  122.     print (gtx("Enter a user name to remove: "));
  123.     }
  124.     chomp(my $answer=<STDIN>);
  125.     push(@names, $answer);
  126. }
  127.  
  128. if (length($names[0]) == 0 || @names > 2) {
  129.     dief (gtx("Only one or two names allowed.\n"));
  130. }
  131.  
  132. if(@names == 2) {      # must be deluserfromgroup
  133.     $action = "deluserfromgroup";
  134.     $user = shift(@names);
  135.     $group = shift(@names);
  136. } else {
  137.     if($action eq "delgroup") {
  138.     $group = shift(@names);
  139.     } else {
  140.     $user = shift(@names);
  141.     }
  142. }
  143.  
  144. undef(@names);
  145.  
  146.  
  147. ##########################################################
  148. # (1) preseed the config
  149. # (2) read the default /etc/adduser.conf configuration.
  150. # (3) read the default /etc/deluser.conf configuration.
  151. # (4) process commmand line settings
  152. # last match wins
  153. ##########################################################
  154.  
  155. preseed_config (\@defaults,\%config);
  156.  
  157. foreach(keys(%pconfig)) {
  158.     $config{$_} = $pconfig{$_} if ($pconfig{$_});
  159. }
  160. undef (%pconfig);
  161.  
  162. if (($config{remove_home} || $config{remove_all_files} || $config{backup}) && ($install_more_packages)) {
  163.     dief (gtx("In order to use the --remove-home, --remove-all-files, and --backup features,
  164. you need to install the `perl-modules' package. To accomplish that, run
  165. apt-get install perl-modules.\n"));
  166. }
  167.  
  168.  
  169. my ($pw_uid, $pw_gid, $pw_homedir, $gr_gid, $maingroup);
  170.  
  171. if($user) {
  172.     #($pw_name,$pw_passwd,$pw_uid,$pw_gid,$pw_quota,$pw_comment,
  173.     # $pw_gecos,$pw_homedir,$pw_shell,$pw_expire) = getpwnam($user);
  174.     my @passwd = getpwnam($user);
  175.     $pw_uid = $passwd[2];
  176.     $pw_gid = $passwd[3];
  177.     $pw_homedir = $passwd[7];
  178.     
  179.     $maingroup = $pw_gid ? getgrgid($pw_gid) : "";
  180. }
  181. if($group) {
  182.     #($gr_name,$gr_passwd,$gr_gid,$gr_members) = getgrnam($group);
  183.     my @group = getgrnam($group);
  184.     $gr_gid = $group[2];
  185. }
  186.  
  187. # arguments are processed:
  188. #
  189. #  $action = "deluser"
  190. #     $user          name of the user to remove
  191. #
  192. #  $action = "delgroup"
  193. #     $group         name of the group to remove
  194. #
  195. #  $action = "deluserfromgroup"
  196. #     $user          the user to be remove
  197. #     $group         the group to remove him/her from
  198.  
  199.  
  200. if($action eq "deluser") {
  201.     &invalidate_nscd();
  202.     
  203.     my($dummy1,$dummy2,$uid);
  204.  
  205.     # Don't allow a non-system user to be deleted when --system is given
  206.     # Also, "user does not exist" is only a warning with --system, but an
  207.     # error without --system.
  208.     if( $config{"system"} ) {
  209.     if( ($dummy1,$dummy2,$uid) = getpwnam($user) ) {
  210.         if ( ($uid < $config{"first_system_uid"} ||
  211.         $uid > $config{"last_system_uid" } ) ) {
  212.         printf (gtx("The user `%s' is not a system user. Exiting.\n"), $user) if $verbose;
  213.         exit 1;
  214.         }
  215.         } else {
  216.         printf (gtx("The user `%s' does not exist, but --system was given. Exiting.\n"), $user) if $verbose;
  217.         exit 0;
  218.     }
  219.     }
  220.     
  221.     unless(exist_user($user)) {
  222.     fail (2,gtx("The user `%s' does not exist.\n"),$user);
  223.     }
  224.  
  225.  
  226.     if($config{"remove_home"} || $config{"remove_all_files"}) {
  227.       s_print (gtx("Looking for files to backup/remove ...\n"));
  228.       my @mountpoints;
  229.       open(MOUNT, "mount |")
  230.           || fail (4 ,gtx("fork for `mount' to parse mount points failed: %s\n", $!));
  231.       while (<MOUNT>) {
  232.           my @temparray = split;
  233.           my $fstype = $temparray[4];
  234.           my $exclude_fstypes = $config{"exclude_fstypes"};
  235.           if (defined($exclude_fstypes)) {
  236.               next if ($fstype =~ /$exclude_fstypes/);
  237.           }
  238.           push @mountpoints,$temparray[2];
  239.       }
  240.       close(MOUNT) or dief (gtx("pipe of command `mount' could not be closed: %s\n",$!));
  241.       my(@files,@dirs);
  242.       if($config{"remove_home"} && ! $config{"remove_all_files"}) {
  243.  
  244.     sub home_match {
  245.       # according to the manpage
  246.       foreach my $mount (@mountpoints) {
  247.         if( $File::Find::name eq $mount ) {
  248.           s_printf (gtx("Not backing up/removing `%s', it is a mount point.\n"),$File::Find::name);
  249.           $File::Find::prune=1;
  250.           return;
  251.         }
  252.       }
  253.       foreach my $re ( split ' ', $config{"no_del_paths"} ) {
  254.         if( $File::Find::name =~ qr/$re/ ) {
  255.           s_printf (gtx("Not backing up/removing `%s', it matches %s.\n"),$File::Find::name,$re);
  256.           $File::Find::prune=1;
  257.           return;
  258.         }
  259.       }
  260.       push(@files, $File::Find::name) 
  261.         if(-f $File::Find::name || -l $File::Find::name);
  262.       push(@dirs, $File::Find::name)
  263.         if(-d $File::Find::name);
  264.     } # sub home_match
  265.     
  266.     File::Find::find({wanted => \&home_match, untaint => 1, no_chdir => 1}, $pw_homedir)
  267.       if(-d "$pw_homedir");
  268.     push(@files, "/var/mail/$user")
  269.       if(-e "/var/mail/$user");
  270.       } else {
  271.     
  272.     sub find_match {
  273.       my ($dev,$ino,$mode,$nlink,$uid,$gid);
  274.       (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
  275.         ($uid == $pw_uid) &&
  276.           (
  277.         ($File::Find::name =~ /^\/proc\// && ($File::Find::prune = 1)) ||
  278.         (-f $File::Find::name && push(@files, $File::Find::name)) ||
  279.         (-d $File::Find::name && push(@dirs, $File::Find::name))
  280.           );
  281.     } # sub find_match
  282.     
  283.     File::Find::find({wanted => \&find_match, untaint => 1, no_chdir => 1}, '/');
  284.       }
  285.  
  286.       if($config{"backup"}) {
  287.       s_printf (gtx("Backing up files to be removed to %s ...\n"),$config{"backup_to"});
  288.       my $filesfile = new File::Temp(TEMPLATE=>"deluser.XXXXX", DIR=>"/tmp");
  289.       my $filesfilename = $filesfile->filename;
  290.       my $backup_name = $config{"backup_to"} . "/$user.tar";
  291.       print "backup_name = $backup_name";
  292.       print $filesfile join("\n",@files);
  293.       $filesfile->close();
  294.          my $tar = &which('tar');
  295.       &systemcall($tar, "-cf", $backup_name, "--files-from", $filesfilename);
  296.       chmod 600, $backup_name;
  297.          my $rootid = 0;
  298.       chown $rootid, $rootid, $backup_name;
  299.       unlink($filesfilename);
  300.          my $bzip2 = &which('bzip2', 1);
  301.          my $gzip = &which('gzip', 1);
  302.       if($bzip2) {
  303.           systemcall($bzip2, $backup_name);
  304.       } elsif($gzip) {
  305.           systemcall($gzip, "--best", $backup_name);
  306.       }
  307.       }
  308.  
  309.       if(@files || @dirs) {
  310.       s_print (gtx("Removing files ...\n"));
  311.       unlink(@files) if(@files);
  312.       foreach(reverse(sort(@dirs))) {
  313.           rmdir($_);
  314.       }
  315.       }
  316.     }
  317.  
  318.     if (system("crontab -l $user >/dev/null 2>&1") == 0) {
  319.       # crontab -l returns 1 if there is no crontab
  320.       my $crontab = &which('crontab');
  321.       &systemcall($crontab, "-r", $user);
  322.       s_print (gtx("Removing crontab ...\n"));
  323.     }
  324.  
  325.     s_printf (gtx("Removing user `%s' ...\n"),$user);
  326.     my $userdel = &which('userdel');
  327.     &systemcall($userdel, $user);
  328.     &invalidate_nscd();
  329.  
  330.     systemcall('/usr/local/sbin/deluser.local', $user, $pw_uid,
  331.                 $pw_gid, $pw_homedir) if (-x "/usr/local/sbin/deluser.local");
  332.  
  333.     s_print (gtx("Done.\n"));
  334.     exit 0;
  335. }
  336.  
  337.     
  338. if($action eq "delgroup") {
  339.     &invalidate_nscd();
  340.     unless(exist_group($group)) {
  341.     fail (3 ,gtx("The group `%s' does not exist.\n"),$group);
  342.     }
  343.     my($dummy,$gid,$members);
  344.     if( !(($dummy, $dummy, $gid, $members ) = getgrnam($group)) ) {
  345.     fail (4 ,gtx("getgrnam `%s' failed. This shouldn't happen.\n"), $group);
  346.     }
  347.     if( $config{"system"} && 
  348.     ($gid < $config{"first_system_gid"} ||
  349.      $gid > $config{"last_system_gid" } )) {
  350.         printf (gtx("The group `%s' is not a system group. Exiting.\n"), $group) if $verbose;
  351.     exit 3;
  352.     }
  353.     if( $config{"only_if_empty"} && $members ne "") {
  354.     fail (5, gtx("The group `%s' is not empty!\n"),$group);
  355.     }
  356.     
  357.     setpwent;
  358.     while ((my $acctname,my $primgrp) = (getpwent)[0,3]) {
  359.     if( $primgrp eq $gr_gid ) {
  360.         fail (7, gtx("`%s' still has `%s' as their primary group!\n"),$acctname,$group);
  361.     }
  362.     }
  363.     endpwent;
  364.  
  365.     s_printf (gtx("Removing group `%s' ...\n"),$group);
  366.     my $groupdel = &which('groupdel');
  367.     &systemcall($groupdel,$group);
  368.     &invalidate_nscd();
  369.     s_print (gtx("Done.\n"));
  370.     exit 0;
  371. }
  372.  
  373.  
  374. if($action eq "deluserfromgroup")
  375. {
  376.     &invalidate_nscd();
  377.     unless(exist_user($user)) {
  378.     fail (2, gtx("The user `%s' does not exist.\n"),$user);
  379.     }
  380.     unless(exist_group($group)) {
  381.     fail (3, gtx("The group `%s' does not exist.\n"),$group);
  382.     }
  383.     if($maingroup eq $group) {
  384.     fail (7, "$0: ",gtx("You may not remove the user from their primary group.\n"));
  385.     }
  386.  
  387.     my @members = get_group_members($group);
  388.     my $ismember = 0;
  389.  
  390.     for(my $i = 0; $i <= $#members; $i++) {
  391.     if($members[$i] eq $user) {
  392.         $ismember = 1;
  393.         splice(@members,$i,1);
  394.     }
  395.     }
  396.  
  397.     unless($ismember) {
  398.     fail (6, gtx("The user `%s' is not a member of group `%s'.\n"),$user,$group);
  399.     }
  400.  
  401.     s_printf (gtx("Removing user `%s' from group `%s' ...\n"),$user,$group);
  402.     #systemcall("usermod","-G", join(",",@groups), $user );
  403.     my $gpasswd = &which('gpasswd');
  404.     &systemcall($gpasswd,'-M', join(',',@members), $group);
  405.     &invalidate_nscd();
  406.     s_print (gtx("Done.\n"));
  407. }
  408.  
  409.  
  410. ######
  411.  
  412. sub fail {
  413.   my ($errorcode, $format, @args) = @_;
  414.   printf STDERR "$0: $format",@args;
  415.   exit $errorcode;
  416.  
  417. }
  418.  
  419. sub version {
  420.     printf (gtx("deluser version %s\n\n"), $version);
  421.     printf (gtx("Removes users and groups from the system.\n"));
  422.     
  423.     printf gtx("Copyright (C) 2000 Roland Bauerschmidt <roland\@copyleft.de>\n\n");
  424.  
  425.     printf gtx("deluser is based on adduser by Guy Maor <maor\@debian.org>, Ian Murdock\n".
  426.       "<imurdock\@gnu.ai.mit.edu> and Ted Hajek <tedhajek\@boombox.micro.umn.edu>\n\n");
  427.  
  428.     printf gtx("This program is free software; you can redistribute it and/or modify
  429. it under the terms of the GNU General Public License as published by
  430. the Free Software Foundation; either version 2 of the License, or (at
  431. your option) any later version.
  432.  
  433. This program is distributed in the hope that it will be useful, but
  434. WITHOUT ANY WARRANTY; without even the implied warranty of
  435. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  436. General Public License, /usr/share/common-licenses/GPL, for more details.\n");
  437. }
  438.  
  439. sub usage {
  440.     printf gtx(
  441. "deluser USER
  442.   remove a normal user from the system
  443.   example: deluser mike
  444.  
  445.   --remove-home             remove the users home directory and mail spool
  446.   --remove-all-files        remove all files owned by user
  447.   --backup                  backup files before removing.
  448.   --backup-to <DIR>         target directory for the backups.
  449.                             Default is the current directory.
  450.   --system                  only remove if system user
  451.  
  452. delgroup GROUP
  453. deluser --group GROUP
  454.   remove a group from the system
  455.   example: deluser --group students
  456.  
  457.   --system                  only remove if system group
  458.   --only-if-empty           only remove if no members left
  459.  
  460. deluser USER GROUP
  461.   remove the user from a group
  462.   example: deluser mike students
  463.  
  464. general options:
  465.   --quiet | -q      don't give process information to stdout
  466.   --help | -h       usage message
  467.   --version | -v    version number and copyright
  468.   --conf | -c FILE  use FILE as configuration file\n\n");
  469. }
  470.  
  471. sub exist_user {
  472.     my $exist_user = shift;
  473.     return(defined getpwnam($exist_user));
  474. }
  475.  
  476. sub exist_group {
  477.     my $exist_group = shift;
  478.     return(defined getgrnam($exist_group));
  479. }
  480.  
  481. # vim:set ai et sts=4 sw=4 tw=0:
  482.